#include<stdio.h>
#include<stdlib.h>

void hex_string(char *hex, int len, char *str)
{
    int i;
    unsigned char *c = hex;
    char tmp[128] = {0};

    for(i = 0; i < len; i++)
    {
        sprintf(tmp,"%02X", c[i]);
        strcat(str, tmp);
    }
}

static int check_length(unsigned int start, unsigned int offset, unsigned int end) {
    if (start + offset >= end) {
        return 0;
    }
    return 1;
}

static int utf8_to_unicode(char *utf8, size_t *utlen, char *unicode, size_t *unlen) 
{
    unsigned int utf8length = strlen(utf8);
    unsigned int utf8_cursor = 0;
	unsigned int uni_cursor = 0;
    unsigned int offset;
    unsigned char* p;
    //unsigned int e;
    unsigned short int e;
	unsigned char*pc;

	//memset(unicode, 0, *unlen);
    while (utf8_cursor < utf8length) {
        p = (unsigned char*)&utf8[utf8_cursor];
		printf("*p = [%02X]\n", *p);
        if (*p < 0xC0) {
            offset = 0;
            e = p[0];
        }
        else if (*p < 0xE0) {
            /*2:<11000000>*/
            offset = 1;
            if (!check_length(utf8_cursor, offset, utf8length)) return 0;
            e = (p[0] & 0x1f) << 6;
            e |= (p[1] & 0x3f);
        }
        else if (*p < 0xF0) {
			printf("%s %d\n", __FUNCTION__, __LINE__);
            /*3:<11100000>*/
            offset = 2;
            if (!check_length(utf8_cursor, offset, utf8length)) return 0;
            e = (p[0] & 0x0f) << 12;
            e |= (p[1] & 0x3f) << 6;
            e |= (p[2] & 0x3f);
			printf("%s %d\n", __FUNCTION__, __LINE__);
        }
        else if (*p < 0xF8) {
            /*4:<11110000>*/
            offset = 3;
            if (!check_length(utf8_cursor, offset, utf8length)) return 0;
            e = (p[0] & 0x07) << 18;
            e |= (p[1] & 0x3f) << 12;
            e |= (p[2] & 0x3f) << 6;
            e |= (p[3] & 0x3f);
        }
        else if (*p < 0xFC) {
            /*5:<11111000>*/
            offset = 4;
            if (!check_length(utf8_cursor, offset, utf8length)) return 0;
            e = (p[0] & 0x03) << 24;
            e |= (p[1] & 0x3f) << 18;
            e |= (p[2] & 0x3f) << 12;
            e |= (p[3] & 0x3f) << 6;
            e |= (p[4] & 0x3f);
        }
        else {
            /*6:<11111100>*/
            offset = 5;
            if (!check_length(utf8_cursor, offset, utf8length)) return 0;
            e = (p[0] & 0x01) << 30;
            e |= (p[1] & 0x3f) << 24;
            e |= (p[2] & 0x3f) << 18;
            e |= (p[3] & 0x3f) << 12;
            e |= (p[4] & 0x3f) << 6;
            e |= (p[5] & 0x3f);
        }
        //unicode.push_back(e);
		printf("%s %d\n", __FUNCTION__, __LINE__);
		printf("e=[%X] sizeof(e)=[%d]\n", e, sizeof(e));
		pc = &e;
		//memcpy(unicode+uni_cursor, &e, sizeof(e));
		unicode[uni_cursor] = pc[1];
		unicode[uni_cursor+1] = pc[0];
		printf("%s %d\n", __FUNCTION__, __LINE__);
		uni_cursor += sizeof(e);
        utf8_cursor += offset + 1;
		printf("%s %d\n", __FUNCTION__, __LINE__);
    }

	*(unicode+uni_cursor) = '\0';
	*unlen = uni_cursor;
	printf("%s %d\n", __FUNCTION__, __LINE__);

    return 1;
}

#if 0
static void unicode_to_utf8(const std::vector<unsigned int> &unicode, std::string &utf8) 
{
    unsigned int unicodelength = unicode.size();
    unsigned int unicode_cursor = 0;
    unsigned int offset;
    unsigned int u;
    unsigned char* e;
    utf8.clear();
    while (unicode_cursor < unicodelength) {
        u = unicode[unicode_cursor];
        if (u < 0x80) {
            offset = 0;
            utf8.push_back(u);
        }
        else if (u < 0x800) {
            /*<11011111> < 000 0000 0000>*/
            offset = 1;
            utf8.push_back(((u >> 6) & 0x1f)|0xc0);
            utf8.push_back((u & 0x3f)|0x80);
        }
        else if(u < 0x10000) {
            /*<11101111> <0000 0000 0000 0000>*/
            offset = 2;
            utf8.push_back(((u >> 12) & 0x0f)|0xe0);
            utf8.push_back(((u >> 6) & 0x3f)|0x80);
            utf8.push_back((u & 0x3f)|0x80);
        }
        else if(u < 0x200000) {
            /*<11110111> <0 0000 0000 0000 0000 0000>*/
            offset = 3;
            utf8.push_back(((u >> 18) & 0x07)|0xf0);
            utf8.push_back(((u >> 12) & 0x3f)|0x80);
            utf8.push_back(((u >> 6) & 0x3f)|0x80);
            utf8.push_back((u & 0x3f)|0x80);
        }
        else if(u < 0x4000000) {
            /*<11111011> <00 0000 0000 0000 0000 0000 0000>*/
            offset = 4;
            utf8.push_back(((u >> 24) & 0x03)|0xf8);
            utf8.push_back(((u >> 18) & 0x3f)|0x80);
            utf8.push_back(((u >> 12) & 0x3f)|0x80);
            utf8.push_back(((u >> 6) & 0x3f)|0x80);
            utf8.push_back((u & 0x3f)|0x80);
        }
        else {
            /*<11111101> <0000 0000 0000 0000 0000 0000 0000 0000>*/
            offset = 5;
            utf8.push_back(((u >> 30) & 0x01)|0xfc);
            utf8.push_back(((u >> 24) & 0x3f)|0x80);
            utf8.push_back(((u >> 18) & 0x3f)|0x80);
            utf8.push_back(((u >> 12) & 0x3f)|0x80);
            utf8.push_back(((u >> 6) & 0x3f)|0x80);
            utf8.push_back((u & 0x3f)|0x80);
        }
        unicode_cursor++;
    }
}

#endif

void print_hex(char *str, int len)
{
	int i;
	unsigned char *c = str;

	printf("hex:[");
	for(i = 0; i < len; i++)
	{
		printf("%02X", c[i]);
	}
	printf("]\n");
}

void main()
{
	//char utf8[256] = "中文";
	char utf8[256] = "无线接入点";
	//char utf8[256] = "パナソニック";
	char unicode[1024] = {0};
	char tmp[1024] = {0};
	size_t utlen = strlen(utf8);
	size_t unlen = sizeof(unicode);

	printf("string=[%s]\n", utf8);
	print_hex(utf8, strlen(utf8));
	utf8_to_unicode(utf8, &utlen, unicode, &unlen); 
	print_hex(unicode, unlen);
	printf("unicode=[%s]\n", unicode);
}

